package com.education.webservlet;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.education.db.domain.InfoFile;
import com.education.service.UploadListener;
import com.education.service.UploadStatus;
import com.education.service.bean.UserBean;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.hibernate.Transaction;

import com.education.db.HibernateSessionFactory;
import com.education.db.dao.InfoFileDAO;

public class FileUploadServlet extends HttpServlet {

    //定义临时文件盒上传文件的存储路径
    private File uploadTemp=null;
    private File uploadPath=null;
    private Transaction tran;

    /**
     * Constructor of the object.
     */
    public FileUploadServlet() {
        super();
    }

    /**
     * Destruction of the servlet. <br>
     */
    public void destroy() {
        super.destroy(); // Just puts "destroy" string in log
        // Put your code here
    }

    /**
     * The doGet method of the servlet. <br>
     *
     * This method is called when a form has its tag value method equals to get.
     *
     * @param request the request send by the client to the server
     * @param response the response send by the server to the client
     * @throws ServletException if an error occurred
     * @throws IOException if an error occurred
     */
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {



        //禁用缓存,index.jsp后台会使用XmlHttpRequest调用本Servlet的doGet方法，从session中获取最新的上传数据情况
        response.setHeader("Cache-Control", "no-store");
        response.setHeader("Pragrma", "no-cache");
        response.setDateHeader("Expires", 0);
        response.setContentType("text/html;charset=utf-8");
        UploadStatus status = (UploadStatus) request.getSession(true)
                .getAttribute("uploadStatus");

        if (status == null) {
            response.getWriter().println("没有上传信息");

            return;
        }
        long startTime = status.getStartTime();
        long currentTime = System.currentTimeMillis();

        // 已传输的时间 单位：s
        long time = (currentTime - startTime) / 1000 + 1;

        // 传输速度 单位：byte/s
        double velocity = ((double) status.getBytesRead()) / (double) time;

        // 估计总时间 单位：s
        double totalTime = status.getContentLength() / velocity;

        // 估计剩余时间 单位：s
        double timeLeft = totalTime - time;

        // 已完成的百分比
        int percent = (int) (100 * (double) status.getBytesRead() / (double) status
                .getContentLength());

        // 已完成数 单位：M
        double length = ((double) status.getBytesRead()) / 1024 / 1024;

        // 总长度 单位：M
        double totalLength = ((double) status.getContentLength()) / 1024 / 1024;

        // 格式：百分比||已完成数(M)||文件总长度(M)||传输速率(K)||已用时间(s)||估计总时间(s)||估计剩余时间(s)||正在上传第几个文件
        String value = percent + "||" + length + "||" + totalLength + "||"
                + velocity + "||" + time + "||" + totalTime + "||" + timeLeft
                + "||" + status.getItems();

        response.getWriter().println(value);
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        tran = HibernateSessionFactory.getSession().getTransaction();
        String datetime = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(Calendar.getInstance().getTime());

        File file=null;
        String description=null;

        //设置响应格式（不设置请求格式，因为文件是二进制的，不能使用UTF-8格式化请求数据）
        response.setContentType("text/html;charset=utf-8");

        PrintWriter out=response.getWriter();
        out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
        out.println("<HTML>");
        out.println("<HEAD><TITLE>文件上传</TITLE></HEAD>");
        out.println("<BODY style='margin:50px'>");
        out.println("上传日志：<BR/>");

        UploadStatus status=new UploadStatus();
        UploadListener listener=new UploadListener(status);
        /*
         * 把 UploadStatus 放到 session 里,引用
		 * 返回与此请求关联的当前HttpSession，如果没有当前会话和创造是真实的，返回一个新的会话。
		 * 如果创建是假的，并要求有没有有效的HttpSession，这个方法返回null。
         */
        request.getSession(true).setAttribute("uploadStatus", status);

        //创建基于磁盘的工厂，针对大文件，临时文件将存储在磁盘
        DiskFileItemFactory factory=new DiskFileItemFactory();
        //设置缓冲区大小,超出该文件直接写入到磁盘的大小设置门槛。
        factory.setSizeThreshold(1024*1024*1024*2);  //这里默认2GB
        //设置用于大于配置的大小阈值设置的临时存储文件目录。
        factory.setRepository(uploadTemp);
        //创建一个文件上传的句柄
        ServletFileUpload upload=new ServletFileUpload(factory);
        //设置最大文件尺寸 ，这里是1GB
        upload.setSizeMax(1024*1024*1024);
        upload.setHeaderEncoding("utf-8");

        // 设置 listener
        upload.setProgressListener(listener);

        UserBean user = (UserBean)request.getSession().getAttribute("UserBean");
        String uploader = user.getPhone();

        String path = request.getParameter("path");
        int index = path.lastIndexOf('\\');
        String folder = path.substring(index+1);
        String folderPath = this.getServletContext().getRealPath("upload");
        //String userPhone = request.getSession().getId();
        File uploadPath1 = new File(folderPath + '\\' + folder + '_' + uploader);
 //       if(!uploadPath1.exists())
            uploadPath1.mkdirs();
//        else
//            out.println();



        tran.begin();

        try {
            //将解析结果放在LIST中
            List<FileItem> list =upload.parseRequest(request);
            out.println("遍历所有的 FileItem ... <br/>");
            // 遍历 list 中所有的 FileItem
            for(FileItem item:list)
            {
                // 如果是 文本域
                if(item.isFormField())
                {
                    if(item.getFieldName().equals("description1")||item.getFieldName().equals("description2"))
                    {

                        description = item.getString("UTF-8");
                        System.out.println("文件名： "+item.getFieldName()+" ----描述-------"+description);
                    }
                }
                else
                {
                    //否则为文件域,当getName为Null说明没有选则文件
                    if((item.getFieldName().equals("file1")||item.getFieldName().equals("file2"))
                            &&item.getName()!=null&&!item.getName().equals(""))
                    {
                        try
                        {
                            // 统一 Linux 与 windows 的路径分隔符
                            String fileName = item.getName();
                            //fileName = fileName.substring(fileName.lastIndexOf("\\"));

                            // 服务器端文件，放在 upload 文件夹下
                            file=new File(uploadPath1,fileName);
                            if(!file.getParentFile().exists())
                                file.getParentFile().mkdirs();
                            if(!file.exists())
                                file.createNewFile();

                            item.write(file);

                            System.out.println("遍历到 "+fileName+" ... <br/>"+description+"<BR/>");

                            InfoFileDAO infoFileDAO = new InfoFileDAO();
                            InfoFile infoFile = new InfoFile();
                            infoFile.setFileName(item.getName());
                            infoFile.setFileUpdater(uploader);
                            infoFile.setFilePath(path);
                            infoFile.setFileDate(Timestamp.valueOf(datetime));
                            infoFileDAO.save(infoFile);
                            tran.commit();
                            //session.clean();

                        } catch (Exception e) {
                            System.out.println("Request 上传失败！"+e.getMessage());
                        }
                        finally //总是立即删除保存表单字段内容的临时文件
                        {
                            item.delete();
                        }
                    }
                }
            }
            System.out.println("Request 解析完毕,文件上传完毕！");
        } catch (Exception e) {
            System.out.println("Request 解析异常！"+e.getMessage());
            tran.rollback();
        }
        out.flush();
        out.close();
    }

    /**
     * Initialization of the servlet. <br>
     *
     * @throws ServletException if an error occurs
     */
    public void init() throws ServletException {

//        String path = request.getParameter("path");
//        int index = ;
//        String uploadFolder =
        uploadPath=new File(this.getServletContext().getRealPath("upload"));
        if(!uploadPath.exists())
            uploadPath.mkdirs();
        uploadTemp=new File(this.getServletContext().getRealPath("upload/temp"));
        if(!uploadTemp.exists())
            uploadTemp.mkdirs();
    }

}
